🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / core / ui / src / commonMain / kotlin / org / meshtastic / core / ui / viewmodel / ConnectionsViewModel.kt
Displaying Raw • Download
core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/viewmodel/ConnectionsViewModel.kt e330442dd5415dc7eb2bff4e3a3f1599c18022a1 (e330442d) Text, 15.36 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.ui.viewmodel
Tff7b72import T7ee787androidx.lifecycle.ViewModel
Tff7b72import T7ee787androidx.lifecycle.viewModelScope
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.StateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.asStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.catch
Tff7b72import T7ee787kotlinx.coroutines.flow.combine
Tff7b72import T7ee787kotlinx.coroutines.flow.distinctUntilChanged
Tff7b72import T7ee787kotlinx.coroutines.flow.filterNotNull
Tff7b72import T7ee787kotlinx.coroutines.flow.flatMapLatest
Tff7b72import T7ee787kotlinx.coroutines.flow.flow
Tff7b72import T7ee787kotlinx.coroutines.flow.flowOf
Tff7b72import T7ee787kotlinx.coroutines.flow.launchIn
Tff7b72import T7ee787kotlinx.coroutines.flow.map
Tff7b72import T7ee787kotlinx.coroutines.flow.onEach
Tff7b72import T7ee787org.koin.core.annotation.KoinViewModel
Tff7b72import T7ee787org.meshtastic.core.common.util.nowMillis
Tff7b72import T7ee787org.meshtastic.core.database.entity.FirmwareRelease
Tff7b72import T7ee787org.meshtastic.core.model.ConnectionState
Tff7b72import T7ee787org.meshtastic.core.model.DeviceHardware
Tff7b72import T7ee787org.meshtastic.core.model.FirmwareUpdateNotice
Tff7b72import T7ee787org.meshtastic.core.model.FirmwareUpdateNoticePolicy
Tff7b72import T7ee787org.meshtastic.core.model.FirmwareUpdateTransport
Tff7b72import T7ee787org.meshtastic.core.model.MyNodeInfo
Tff7b72import T7ee787org.meshtastic.core.model.Node
Tff7b72import T7ee787org.meshtastic.core.model.util.TimeConstants
Tff7b72import T7ee787org.meshtastic.core.repository.DeviceHardwareRepository
Tff7b72import T7ee787org.meshtastic.core.repository.FirmwareReleaseRepository
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRestartTracker
Tff7b72import T7ee787org.meshtastic.core.repository.Notification
Tff7b72import T7ee787org.meshtastic.core.repository.NotificationManager
Tff7b72import T7ee787org.meshtastic.core.repository.RadioConfigRepository
Tff7b72import T7ee787org.meshtastic.core.repository.RadioPrefs
Tff7b72import T7ee787org.meshtastic.core.repository.ServiceRepository
Tff7b72import T7ee787org.meshtastic.core.repository.UiPrefs
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_available
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_notification_android
Tff7b72import T7ee787org.meshtastic.core.resources.firmware_update_notification_flasher
Tff7b72import T7ee787org.meshtastic.core.resources.getStringSuspend
Tff7b72import T7ee787org.meshtastic.proto.Config
Tff7b72import T7ee787org.meshtastic.proto.LocalConfig
T8b949e/**
* Derived, UI-friendly summary of the device connection state. Combines [ServiceRepository.connectionState] with
* "region unset" and the [ServiceRepository.RECONNECTING_PROGRESS_TEXT] handshake-recovery signal to surface cases
* (MUST_SET_REGION, RECONNECTING) that otherwise need separate boolean flags in the UI layer.
*/
Tff7b72enum Tff7b72class T56d364ConnectionStatus Tb4b4b4{
T8b949e/** No device has been selected or we are otherwise disconnected. */
Te6edf3NOT_CONNECTEDTb4b4b4,
T8b949e/** A device has been selected and we are working through bonding/handshake. */
Te6edf3CONNECTINGTb4b4b4,
T8b949e/**
* Transport is recovering from a WiFi/TCP handshake stall (the watchdog tore the link down and is bringing it back
* up). Distinct from [NOT_CONNECTED] so the UI can show an in-progress recovery instead of a final failure.
*/
Te6edf3RECONNECTINGTb4b4b4,
T8b949e/**
* The node is applying a change that reboots it (config save or reboot command) and the transport drop is expected.
* Distinct from [NOT_CONNECTED] so the UI presents an in-progress restart instead of a failure. Ends when the node
* finishes its post-reboot handshake or the [NodeRestartTracker] window expires.
*/
Te6edf3RESTARTINGTb4b4b4,
T8b949e/** Connected with node info available. */
Te6edf3CONNECTEDTb4b4b4,
T8b949e/** Connected but the device is in deep sleep. */
Te6edf3CONNECTED_SLEEPINGTb4b4b4,
T8b949e/** Connected and active, but LoRa region is UNSET — user action required. */
Te6edf3MUST_SET_REGIONTb4b4b4,
Tb4b4b4}
Tf0883e@KoinViewModel
Tff7b72class T56d364ConnectionsViewModelTb4b4b4(
Te6edf3radioConfigRepositoryTb4b4b4: Te6edf3RadioConfigRepositoryTb4b4b4,
Te6edf3serviceRepositoryTb4b4b4: Te6edf3ServiceRepositoryTb4b4b4,
Te6edf3nodeRepositoryTb4b4b4: Te6edf3NodeRepositoryTb4b4b4,
Te6edf3nodeRestartTrackerTb4b4b4: Te6edf3NodeRestartTrackerTb4b4b4,
Tff7b72private Tff7b72val Te6edf3uiPrefsTb4b4b4: Te6edf3UiPrefsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3deviceHardwareRepositoryTb4b4b4: Te6edf3DeviceHardwareRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3firmwareReleaseRepositoryTb4b4b4: Te6edf3FirmwareReleaseRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3radioPrefsTb4b4b4: Te6edf3RadioPrefsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3notificationManagerTb4b4b4: Te6edf3NotificationManagerTb4b4b4,
Tb4b4b4) Tb4b4b4: Te6edf3ViewModelTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3scheduledFirmwareUpdateNotificationKeys Tff7b72= Te6edf3mutableSetOfTff7b72<Tffa657StringTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3localConfigTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3LocalConfigTff7b72> Tff7b72=
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3localConfigFlowTb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Te6edf3LocalConfigTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3connectionState Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3connectionState
Tff7b72val Te6edf3lockdownState Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3lockdownState
Tff7b72val Te6edf3sessionAuthorized Tff7b72= Te6edf3serviceRepositoryTb4b4b4.Te6edf3sessionAuthorized
Tff7b72val Te6edf3myNodeInfoTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3MyNodeInfo?Tff7b72> Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfo
Tff7b72val Te6edf3ourNodeInfoTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3Node?Tff7b72> Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3ourNodeInfo
T8b949e/**
* Filtered [ourNodeInfo] that only emits when display-relevant fields change, preventing continuous recomposition
* from lastHeard/snr updates.
*/
Tff7b72val Te6edf3ourNodeForDisplayTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3Node?Tff7b72> Tff7b72=
Te6edf3nodeRepositoryTb4b4b4.Te6edf3ourNodeInfo
Tb4b4b4.Te6edf3distinctUntilChanged Tb4b4b4{ Te6edf3oldTb4b4b4, Te6edf3new Tff7b72-Tff7b72>
Te6edf3oldTff7b72?.Te6edf3num Tff7b72=Tff7b72= Te6edf3newTff7b72?.Te6edf3num Tff7b72&Tff7b72&
Te6edf3oldTff7b72?.Te6edf3user Tff7b72=Tff7b72= Te6edf3newTff7b72?.Te6edf3user Tff7b72&Tff7b72&
Te6edf3oldTff7b72?.Te6edf3batteryLevel Tff7b72=Tff7b72= Te6edf3newTff7b72?.Te6edf3batteryLevel Tff7b72&Tff7b72&
Te6edf3oldTff7b72?.Te6edf3voltage Tff7b72=Tff7b72= Te6edf3newTff7b72?.Te6edf3voltage Tff7b72&Tff7b72&
Te6edf3oldTff7b72?.Te6edf3metadataTff7b72?.Te6edf3firmware_version Tff7b72=Tff7b72= Te6edf3newTff7b72?.Te6edf3metadataTff7b72?.Te6edf3firmware_version
Tb4b4b4}
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3ourNodeInfoTb4b4b4.Te6edf3valueTb4b4b4)
T8b949e/** Whether the LoRa region is UNSET and needs to be configured. */
Tff7b72val Te6edf3regionUnsetTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72=
Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3localConfigFlow
Tb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3loraTff7b72?.Te6edf3region Tff7b72=Tff7b72= Te6edf3ConfigTb4b4b4.Te6edf3LoRaConfigTb4b4b4.Te6edf3RegionCodeTb4b4b4.Te6edf3UNSET Tb4b4b4}
Tb4b4b4.Te6edf3distinctUntilChangedTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Tff7b72falseTb4b4b4)
T8b949e/**
* Single source of truth for the UI's "connection status" pill/banner. Derived from [connectionState],
* [ServiceRepository.connectionProgress], and [regionUnset]; kept here rather than in the composable so the mapping
* is observable and testable.
*
* The [ConnectionStatus.RECONNECTING] case is signalled by the WiFi/TCP handshake watchdog writing
* [ServiceRepository.RECONNECTING_PROGRESS_TEXT] to [ServiceRepository.connectionProgress] immediately before its
* recovery sibling transitions to [ConnectionState.Disconnected]. See
* [ServiceRepository.RECONNECTING_PROGRESS_TEXT] for the cross-track contract.
*/
Tff7b72val Te6edf3connectionStatusTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ConnectionStatusTff7b72> Tff7b72=
Te6edf3combineTb4b4b4(
Te6edf3connectionStateTb4b4b4,
Te6edf3regionUnsetTb4b4b4,
Te6edf3serviceRepositoryTb4b4b4.Te6edf3connectionProgressTb4b4b4,
Te6edf3nodeRestartTrackerTb4b4b4.Te6edf3restartExpectedTb4b4b4,
Tb4b4b4) Tb4b4b4{ Te6edf3stateTb4b4b4, Te6edf3unsetTb4b4b4, Te6edf3progressTb4b4b4, Te6edf3restartExpected Tff7b72-Tff7b72>
Tff7b72when Tb4b4b4(Te6edf3stateTb4b4b4) Tb4b4b4{
Tff7b72is Te6edf3ConnectionStateTb4b4b4.Te6edf3Connected Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3unsetTb4b4b4) Te6edf3ConnectionStatusTb4b4b4.Te6edf3MUST_SET_REGION Tff7b72else Te6edf3ConnectionStatusTb4b4b4.Te6edf3CONNECTED
T8b949e// While an expected node restart is in flight, the drop and the reconnect attempts are the restart
T8b949e// —
T8b949e// present them as such instead of as a failure.
Te6edf3ConnectionStateTb4b4b4.Te6edf3Connecting Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3restartExpectedTb4b4b4) Te6edf3ConnectionStatusTb4b4b4.Te6edf3RESTARTING Tff7b72else Te6edf3ConnectionStatusTb4b4b4.Te6edf3CONNECTING
Te6edf3ConnectionStateTb4b4b4.Te6edf3Disconnected Tff7b72-Tff7b72>
Tff7b72when Tb4b4b4{
Te6edf3restartExpected Tff7b72-Tff7b72> Te6edf3ConnectionStatusTb4b4b4.Te6edf3RESTARTING
Te6edf3progress Tff7b72=Tff7b72= Te6edf3ServiceRepositoryTb4b4b4.Te6edf3RECONNECTING_PROGRESS_TEXT Tff7b72-Tff7b72> Te6edf3ConnectionStatusTb4b4b4.Te6edf3RECONNECTING
Tff7b72else Tff7b72-Tff7b72> Te6edf3ConnectionStatusTb4b4b4.Te6edf3NOT_CONNECTED
Tb4b4b4}
Te6edf3ConnectionStateTb4b4b4.Te6edf3DeviceSleep Tff7b72-Tff7b72> Te6edf3ConnectionStatusTb4b4b4.Te6edf3CONNECTED_SLEEPING
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3distinctUntilChangedTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Te6edf3ConnectionStatusTb4b4b4.Te6edf3NOT_CONNECTEDTb4b4b4)
Tff7b72private Tff7b72val Te6edf3_hasShownNotPairedWarning Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Te6edf3uiPrefsTb4b4b4.Te6edf3hasShownNotPairedWarningTb4b4b4.Te6edf3valueTb4b4b4)
Tff7b72val Te6edf3hasShownNotPairedWarningTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657BooleanTff7b72> Tff7b72= Te6edf3_hasShownNotPairedWarningTb4b4b4.Te6edf3asStateFlowTb4b4b4(Tb4b4b4)
Tff7b72fun Td2a8ffsuppressNoPairedWarningTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_hasShownNotPairedWarningTb4b4b4.Te6edf3value Tff7b72= Tff7b72true
Te6edf3uiPrefsTb4b4b4.Te6edf3setHasShownNotPairedWarningTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3localHardware Tff7b72=
Te6edf3combineTb4b4b4(Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4, Te6edf3nodeRepositoryTb4b4b4.Te6edf3ourNodeInfoTb4b4b4) Tb4b4b4{ Te6edf3myNodeTb4b4b4, Te6edf3ourNode Tff7b72-Tff7b72>
Tff7b72val Te6edf3hardwareModel Tff7b72= Te6edf3ourNodeTff7b72?.Te6edf3userTff7b72?.Te6edf3hw_modelTff7b72?.Te6edf3value Tff7b72?: Tff7b72returnTf0883e@combine Tff7b72null
Tff7b72val Te6edf3target Tff7b72= Te6edf3myNodeTff7b72?.Te6edf3pioEnvTff7b72?.Te6edf3takeIf Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isNotBlankTb4b4b4(Tb4b4b4) Tb4b4b4}
Te6edf3hardwareModel Te6edf3to Te6edf3target
Tb4b4b4}
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Te6edf3query Tff7b72-Tff7b72>
Te6edf3queryTff7b72?.Te6edf3let Tb4b4b4{ Tb4b4b4(Te6edf3hardwareModelTb4b4b4, Te6edf3targetTb4b4b4) Tff7b72-Tff7b72>
Te6edf3deviceHardwareRepositoryTb4b4b4.Te6edf3observeDeviceHardwareTb4b4b4(Te6edf3hardwareModelTb4b4b4, Te6edf3targetTb4b4b4)
Tb4b4b4} Tff7b72?: Te6edf3flowOfTb4b4b4(Tff7b72nullTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3firmwareUpdateInputs Tff7b72=
Te6edf3combineTb4b4b4(
Te6edf3connectionStateTb4b4b4,
Te6edf3nodeRepositoryTb4b4b4.Te6edf3myIdTb4b4b4,
Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4,
Te6edf3firmwareReleaseRepositoryTb4b4b4.Te6edf3stableReleaseTb4b4b4,
Te6edf3radioPrefsTb4b4b4.Te6edf3devAddrTb4b4b4,
Tb4b4b4) Tb4b4b4{ Te6edf3stateTb4b4b4, Te6edf3nodeIdentityTb4b4b4, Te6edf3myNodeTb4b4b4, Te6edf3stableReleaseTb4b4b4, Te6edf3address Tff7b72-Tff7b72>
Te6edf3FirmwareUpdateInputsTb4b4b4(
Te6edf3connectionState Tff7b72= Te6edf3stateTb4b4b4,
Te6edf3nodeIdentity Tff7b72= Te6edf3nodeIdentityTb4b4b4,
Te6edf3currentVersion Tff7b72= Te6edf3myNodeTff7b72?.Te6edf3firmwareVersionTb4b4b4,
T8b949e// A stale (or failed-to-refresh) release catalog must not prompt users. The repository updates this
T8b949e// timestamp only when it writes a current catalog; its bundled seed and a successful refresh are
T8b949e// both valid sources, while an old cache fails closed.
Te6edf3stableRelease Tff7b72=
Te6edf3stableReleaseTff7b72?.Te6edf3takeIf Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3lastUpdated Tff7b72>Tff7b72= Te6edf3nowMillis Tff7b72- Te6edf3TimeConstantsTb4b4b4.Te6edf3ONE_HOURTb4b4b4.Te6edf3inWholeMilliseconds Tb4b4b4}Tb4b4b4,
Te6edf3address Tff7b72= Te6edf3addressTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72val Te6edf3firmwareUpdateCandidate Tff7b72=
Te6edf3combineTb4b4b4(Te6edf3firmwareUpdateInputsTb4b4b4, Te6edf3localHardwareTb4b4b4) Tb4b4b4{ Te6edf3inputsTb4b4b4, Te6edf3hardware Tff7b72-Tff7b72>
Tff7b72val Te6edf3state Tff7b72= Te6edf3inputsTb4b4b4.Te6edf3connectionState
Tff7b72if Tb4b4b4(Te6edf3state Tff7b72!is Te6edf3ConnectionStateTb4b4b4.Te6edf3ConnectedTb4b4b4) Tff7b72returnTf0883e@combine Tff7b72null
Tff7b72val Te6edf3transport Tff7b72= Te6edf3inputsTb4b4b4.Te6edf3addressTff7b72?.Te6edf3firstOrNullTb4b4b4(Tb4b4b4)Tff7b72?.Te6edf3toFirmwareUpdateTransportTb4b4b4(Tb4b4b4) Tff7b72?: Tff7b72returnTf0883e@combine Tff7b72null
Tff7b72val Te6edf3stableRelease Tff7b72= Te6edf3inputsTb4b4b4.Te6edf3stableRelease Tff7b72?: Tff7b72returnTf0883e@combine Tff7b72null
Tff7b72val Te6edf3deviceHardware Tff7b72= Te6edf3hardware Tff7b72?: Tff7b72returnTf0883e@combine Tff7b72null
Te6edf3FirmwareUpdateCandidateTb4b4b4(
Te6edf3nodeIdentity Tff7b72= Te6edf3inputsTb4b4b4.Te6edf3nodeIdentityTb4b4b4,
Te6edf3currentVersion Tff7b72= Te6edf3inputsTb4b4b4.Te6edf3currentVersionTb4b4b4,
Te6edf3stableRelease Tff7b72= Te6edf3stableReleaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3deviceHardwareTb4b4b4,
Te6edf3transport Tff7b72= Te6edf3transportTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3firmwareUpdateNoticeTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3FirmwareUpdateNotice?Tff7b72> Tff7b72=
Te6edf3firmwareUpdateCandidate
Tb4b4b4.Te6edf3flatMapLatest Tb4b4b4{ Te6edf3candidate Tff7b72-Tff7b72>
Te6edf3candidateTff7b72?.Te6edf3let Tb4b4b4{
Te6edf3flow Tb4b4b4{
Tff7b72val Te6edf3releaseTargets Tff7b72=
Te6edf3firmwareReleaseRepositoryTb4b4b4.Te6edf3getManifestTargetsTb4b4b4(Tffa657itTb4b4b4.Te6edf3stableReleaseTb4b4b4) Tff7b72?: Te6edf3emptySetTb4b4b4(Tb4b4b4)
Te6edf3emitTb4b4b4(
Te6edf3FirmwareUpdateNoticePolicyTb4b4b4.Te6edf3createNoticeTb4b4b4(
Te6edf3nodeIdentity Tff7b72= Tffa657itTb4b4b4.Te6edf3nodeIdentityTb4b4b4,
Te6edf3currentVersion Tff7b72= Tffa657itTb4b4b4.Te6edf3currentVersionTb4b4b4,
Te6edf3stableVersion Tff7b72= Tffa657itTb4b4b4.Te6edf3stableReleaseTb4b4b4.Te6edf3idTb4b4b4,
Te6edf3hardware Tff7b72= Tffa657itTb4b4b4.Te6edf3hardwareTb4b4b4,
Te6edf3transport Tff7b72= Tffa657itTb4b4b4.Te6edf3transportTb4b4b4,
Te6edf3releaseTargets Tff7b72= Te6edf3releaseTargetsTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3catch Tb4b4b4{ Te6edf3emitTb4b4b4(Tff7b72nullTb4b4b4) Tb4b4b4}
Tb4b4b4} Tff7b72?: Te6edf3flowOfTb4b4b4(Tff7b72nullTb4b4b4)
Tb4b4b4}
Tb4b4b4.Te6edf3distinctUntilChangedTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3stateInWhileSubscribedTb4b4b4(Te6edf3initialValue Tff7b72= Tff7b72nullTb4b4b4)
Tff7b72init Tb4b4b4{
Te6edf3firmwareUpdateNotice
Tb4b4b4.Te6edf3map Tb4b4b4{ Te6edf3notice Tff7b72-Tff7b72>
Te6edf3noticeTff7b72?.Te6edf3takeIf Tb4b4b4{
Te6edf3FirmwareUpdateNoticePolicyTb4b4b4.Te6edf3shouldScheduleTb4b4b4(
Tffa657itTb4b4b4.Te6edf3notificationKeyTb4b4b4,
Te6edf3uiPrefsTb4b4b4.Te6edf3firmwareUpdateNotificationKeysTb4b4b4.Te6edf3valueTb4b4b4,
Tb4b4b4) Tff7b72&Tff7b72& Tffa657itTb4b4b4.Te6edf3notificationKey Tff7b72!in Te6edf3scheduledFirmwareUpdateNotificationKeys
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3filterNotNullTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3onEach Tb4b4b4{ Te6edf3notice Tff7b72-Tff7b72>
Tff7b72val Te6edf3message Tff7b72=
Tff7b72when Tb4b4b4(Te6edf3noticeTb4b4b4.Te6edf3destinationTb4b4b4) Tb4b4b4{
Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3modelTb4b4b4.Te6edf3FirmwareUpdateDestinationTb4b4b4.Te6edf3AndroidUpdate Tff7b72-Tff7b72>
Te6edf3getStringSuspendTb4b4b4(
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_notification_androidTb4b4b4,
Te6edf3noticeTb4b4b4.Te6edf3currentVersionTb4b4b4,
Te6edf3noticeTb4b4b4.Te6edf3stableVersionTb4b4b4,
Tb4b4b4)
Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3modelTb4b4b4.Te6edf3FirmwareUpdateDestinationTb4b4b4.Te6edf3MeshtasticFlasher Tff7b72-Tff7b72>
Te6edf3getStringSuspendTb4b4b4(
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_notification_flasherTb4b4b4,
Te6edf3noticeTb4b4b4.Te6edf3currentVersionTb4b4b4,
Te6edf3noticeTb4b4b4.Te6edf3stableVersionTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72if Tb4b4b4(
Te6edf3notificationManagerTb4b4b4.Te6edf3dispatchTb4b4b4(
Te6edf3NotificationTb4b4b4(
Te6edf3id Tff7b72= Te6edf3noticeTb4b4b4.Te6edf3notificationKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3title Tff7b72= Te6edf3getStringSuspendTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3firmware_update_availableTb4b4b4)Tb4b4b4,
Te6edf3message Tff7b72= Te6edf3messageTb4b4b4,
Te6edf3type Tff7b72= Te6edf3NotificationTb4b4b4.Te6edf3TypeTb4b4b4.Te6edf3InfoTb4b4b4,
Te6edf3category Tff7b72= Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3NodeEventTb4b4b4,
Te6edf3deepLinkUri Tff7b72=
Tff7b72if Tb4b4b4(
Te6edf3noticeTb4b4b4.Te6edf3destination Tff7b72=Tff7b72=
Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3modelTb4b4b4.Te6edf3FirmwareUpdateDestinationTb4b4b4.Te6edf3AndroidUpdate
Tb4b4b4) Tb4b4b4{
Ta5d6ff"Ta5d6ffmeshtastic:///firmware/updateTa5d6ff"
Tb4b4b4} Tff7b72else Tb4b4b4{
Ta5d6ff"Ta5d6ffhttps://flasher.meshtastic.orgTa5d6ff"
Tb4b4b4}Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4) Tb4b4b4{
Te6edf3scheduledFirmwareUpdateNotificationKeys Tff7b72+Tff7b72= Te6edf3noticeTb4b4b4.Te6edf3notificationKey
Te6edf3uiPrefsTb4b4b4.Te6edf3recordFirmwareUpdateNotificationKeyTb4b4b4(Te6edf3noticeTb4b4b4.Te6edf3notificationKeyTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3launchInTb4b4b4(Te6edf3viewModelScopeTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72data Tff7b72class T56d364FirmwareUpdateInputsTb4b4b4(
Tff7b72val Te6edf3connectionStateTb4b4b4: Te6edf3ConnectionStateTb4b4b4,
Tff7b72val Te6edf3nodeIdentityTb4b4b4: Tffa657String?Tb4b4b4,
Tff7b72val Te6edf3currentVersionTb4b4b4: Tffa657String?Tb4b4b4,
Tff7b72val Te6edf3stableReleaseTb4b4b4: Te6edf3FirmwareRelease?Tb4b4b4,
Tff7b72val Te6edf3addressTb4b4b4: Tffa657String?Tb4b4b4,
Tb4b4b4)
Tff7b72private Tff7b72data Tff7b72class T56d364FirmwareUpdateCandidateTb4b4b4(
Tff7b72val Te6edf3nodeIdentityTb4b4b4: Tffa657String?Tb4b4b4,
Tff7b72val Te6edf3currentVersionTb4b4b4: Tffa657String?Tb4b4b4,
Tff7b72val Te6edf3stableReleaseTb4b4b4: Te6edf3FirmwareReleaseTb4b4b4,
Tff7b72val Te6edf3hardwareTb4b4b4: Te6edf3DeviceHardwareTb4b4b4,
Tff7b72val Te6edf3transportTb4b4b4: Te6edf3FirmwareUpdateTransportTb4b4b4,
Tb4b4b4)
Tff7b72private Tff7b72fun Te6edf3CharTb4b4b4.Td2a8fftoFirmwareUpdateTransportTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3FirmwareUpdateTransport? Tff7b72= Tff7b72when Tb4b4b4(Tff7b72thisTb4b4b4) Tb4b4b4{
Ta5d6ff'x' Tff7b72-Tff7b72> Te6edf3FirmwareUpdateTransportTb4b4b4.Te6edf3Bluetooth
Ta5d6ff's' Tff7b72-Tff7b72> Te6edf3FirmwareUpdateTransportTb4b4b4.Te6edf3Serial
Ta5d6ff't' Tff7b72-Tff7b72> Te6edf3FirmwareUpdateTransportTb4b4b4.Te6edf3Tcp
Tff7b72else Tff7b72-Tff7b72> Tff7b72null
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.08s